// .........................................................................
// Title: idiosyncrasy.do
//
// Performs analysis quantifying the level of idiosyncrasy in the holdings
// of insurers and investment funds at the security level
// .........................................................................

* ---------------------------------------
* Insurer holdings of top 500 bonds
* ---------------------------------------

* Get set of top 500 bonds
use "$tmp/trace_with_characteristics_holdings_complete_m", clear
keep if inlist(rating_cat, "AAA", "AA", "A", "BBB")
gen issuance_m = mofd(issuance_date)
gen maturity_m = mofd(maturity_date)
format %tm issuance_date maturity_date
drop if missing(issuance_m) | missing(maturity_m)
keep if issuance_m <= tm(2017m12) & maturity_m >= tm(2017m12)
keep if date_m == tm(2017m12)
drop if missing(value_outstanding_mv)
gsort -value_outstanding_mv
keep if _n <= 500
keep cusip
save "$tmp/_ig_top500", replace

* Read size ranks
use "$tmp/insurer_avg_rank_full", clear
keep holder_name insurer_avg_rank
rename insurer_avg_rank size_rank
save "$tmp/size_ranks", replace 

* Construct share of bonds held within set, add insurer size rank
use "$tmp/insurance_corporate_bond_holdings_x.dta", clear
keep if date_q == tq(2017q4)
mmerge cusip using "$tmp/_ig_top500", unmatched(m)
keep if _merge == 3
gcollapse (sum) clean_, by(holder_name cusip)
gen count = 1
gcollapse (sum) count clean_, by(holder_name)
mmerge holder_name using "$tmp/size_ranks", unmatched(m)
drop _merge
gen share_bonds_held = count / 500
gsort size_rank
save "$tmp/insurer_share_bonds_held", replace

* --------------------------------------------
* Set of SP500 equities
* --------------------------------------------

* Get sp500 set from SPDR S&P 500 ETF holdings
use "$morningstar_hd/HD_2017_y.dta" if MasterPortfolio == 14193, clear
gsort date_q cusip
by date_q cusip: keep if _n == 1
keep date_q cusip
gen sp500 = 1
by date_q: gen N = _N
by date_q: gen n = _n
drop n N
save "$tmp/sp500_constituents_q", replace

* Count of index members
use "$tmp/sp500_constituents_q", clear
gcollapse (sum) sp500, by(date_q)
rename sp500 sp500_count
save "$tmp/sp500_constituents_q_count", replace

* ---------------------------------------
* Unwind holdings of equities via funds
* ---------------------------------------

* Mapping between Morningstar MPID and CUSIP
use "$output/morningstar_mapping/morningstar_mapping_full.dta", clear
rename CUSIP cusip
keep cusip MasterPortfolioId_mapping
rename MasterPortfolioId_mapping MasterPortfolioId
drop if missing(cusip)
drop if cusip == "NULL"
duplicates drop
bys cusip: keep if _n == 1 // NB: 99.95% are unique
gsort cusip
save "$tmp/cusip_to_mpid", replace

* Get insurer holdings of fund shares
use "$insurance_holdings/all_insurance_master", clear
drop if missing(cusip)
mmerge cusip using "$tmp/cusip_to_mpid", unmatched(m)
drop if missing(investing_mpid)
drop _merge
rename investing_mpid MasterPortfolioId
destring MasterPortfolioId, replace
mmerge MasterPortfolioId using "$output/morningstar_mapping/morningstar_mapping_uniqueonly.dta", unmatched(m)
drop _merge
save "$tmp/insurance_holdings_of_funds", replace

* Construct catalog of unique MPIDs held
use "$tmp/insurance_holdings_of_funds", clear
keep MasterPortfolioId
bys MasterPortfolioId: keep if _n == 1
drop if missing(MasterPortfolioId)
save "$tmp/insurance_holdings_of_funds_mpids_catalog", replace

* Get portfolios of the relevant funds
use "$tmp/fund_holdings/HD_all_q_compact", clear
mmerge MasterPortfolioId using "$tmp/insurance_holdings_of_funds_mpids_catalog", unmatched(m)
keep if _merge == 3
drop _merge
order MasterPortfolioId date_q
gsort MasterPortfolioId date_q
by MasterPortfolioId date_q: egen totVal = total(marketvalue_usd)
gen portfolio_share = marketvalue_usd / totVal
save "$tmp/fund_holdings_for_insurance_unwind", replace

* Unwind the holdings of equities via fund shares
use "$tmp/insurance_holdings_of_funds", clear
mmerge MasterPortfolioId date_q using "$tmp/fund_holdings_for_insurance_unwind", unmatched(m) uname(uw_)
keep if _merge == 3
rename cusip uw_fund_cusip
rename MasterPortfolioId uw_fund_mpid
rename uw_cusip cusip
replace marketvalue_usd = marketvalue_usd * uw_portfolio_share
order holder_name date_q cusip
drop uw_portfolio_share
drop uw_fund_cusip
gcollapse (sum) marketvalue_usd (firstnm) uw_fund_mpid, by(holder_name date_q cusip)

* Save data for 2017q4
keep if date_q == tq(2017q4)
save "$tmp/insurance_holdings_unwind_addendum_2017q4", replace

* ---------------------------------------
* Insurer holdings of sp500 equities
* ---------------------------------------

* Merge direct and indirect equity holdings, collapse at issuer-security level
use "$tmp/insurer_equity_holdings" if date_q == tq(2017q4), replace
append using "$tmp/insurance_holdings_unwind_addendum_2017q4"
gcollapse (sum) marketvalue_usd, by(holder_name cusip date_q)

* Subset on sp500 component
mmerge cusip date_q using "$tmp/sp500_constituents_q", unmatched(m)
keep if _merge == 3

* Construct share of equities held within set, add size rank
gen count = 1
gcollapse (sum) count, by(holder_name date_q)
mmerge date_q using "$tmp/sp500_constituents_q_count", unmatched(m)
mmerge holder_name using "$tmp/size_ranks", unmatched(m)
gen share_stocks_held = count / sp500_count
gsort size_rank
save "$tmp/insurer_share_stocks_held", replace

* -------------------------------------------
* Plot series for bonds and equities together
* -------------------------------------------

* Construct and output plot (Figure 7)
use "$tmp/insurer_share_stocks_held", clear
mmerge size_rank using "$tmp/insurer_share_bonds_held.dta", unmatched(m) uname(b_)
drop _merge
gsort size_rank
rename b_share_bonds_held share_bonds_held

scatter share_stocks_held share_bonds_held size_rank if size_rank <= 300, graphregion(color(white)) xtitle("Insurer Size Rank") ///
    ytitle("Share Held (By Count)") mcolor(red%40 blue%15) msize(medlarge medlarge) ///
        || lowess share_stocks_held size_rank if size_rank <= 300, lcolor(red) lwidth(medthick) bwidth(.4) ///
        || lowess share_bonds_held size_rank if size_rank <= 300, lcolor(blue) lwidth(medthick) bwidth(.4) ///
    legend(label(3 "S&P 500 Equities") label(4 "Top 500 Investment-Grade Bonds") ///
        order(3 4) cols(2)) xsize(7) ylab(0(.2)1, angle(0))

graph export "$graphs/holdings_idiosyncrasy_insurers.pdf", as(pdf) replace

* ---------------------------------------------
* Construct versions with smaller sets of bonds
* ---------------------------------------------

* Top 100 bonds
use "$tmp/trace_with_characteristics_holdings_complete_m", clear
keep if inlist(rating_cat, "AAA", "AA", "A", "BBB")
gen issuance_m = mofd(issuance_date)
gen maturity_m = mofd(maturity_date)
format %tm issuance_date maturity_date
drop if missing(issuance_m) | missing(maturity_m)
keep if issuance_m <= tm(2017m12) & maturity_m >= tm(2017m12)
keep if date_m == tm(2017m12)
drop if missing(value_outstanding_mv)
gsort -value_outstanding_mv
keep if _n <= 100
keep cusip
save "$tmp/_ig_top100", replace

* Top 250 bonds
use "$tmp/trace_with_characteristics_holdings_complete_m", clear
gen issuance_m = mofd(issuance_date)
gen maturity_m = mofd(maturity_date)
format %tm issuance_date maturity_date
drop if missing(issuance_m) | missing(maturity_m)
keep if issuance_m <= tm(2017m12) & maturity_m >= tm(2017m12)
keep if date_m == tm(2017m12)
drop if missing(value_outstanding_mv)
gsort -value_outstanding_mv
keep if _n <= 250
keep cusip
save "$tmp/_ig_top250", replace

* Shares for top 100
use "$tmp/insurance_corporate_bond_holdings_x.dta", clear
keep if date_q == tq(2017q4)
mmerge cusip using "$tmp/_ig_top100", unmatched(m)
keep if _merge == 3
gcollapse (sum) clean_, by(holder_name cusip)
gen count = 1
gcollapse (sum) count clean_, by(holder_name)
mmerge holder_name using "$tmp/size_ranks", unmatched(m)
drop _merge
gen share_bonds_held_100 = count / 100
gsort size_rank
save "$tmp/insurer_share_bonds_held_100", replace

* Shares for top 250
use "$tmp/insurance_corporate_bond_holdings_x.dta", clear
keep if date_q == tq(2017q4)
mmerge cusip using "$tmp/_ig_top250", unmatched(m)
keep if _merge == 3
gcollapse (sum) clean_, by(holder_name cusip)
gen count = 1
gcollapse (sum) count clean_, by(holder_name)
mmerge holder_name using "$tmp/size_ranks", unmatched(m)
drop _merge
gen share_bonds_held_250 = count / 250
gsort size_rank
save "$tmp/insurer_share_bonds_held_250", replace

* Merge and plot
use "$tmp/insurer_share_bonds_held_100", clear
mmerge size_rank using "$tmp/insurer_share_bonds_held_250"
drop _merge
gsort size_rank
keep if size_rank <= 300

scatter share_bonds_held_100 share_bonds_held_250 size_rank, graphregion(color(white)) xtitle("Insurer Size Rank") ///
    ytitle("Share Held (By Count)") mcolor(orange%70 blue%15) msymbol(dh) msize(medlarge medlarge) ///
        || lowess share_bonds_held_100 size_rank, lcolor(orange) lwidth(medthick) bwidth(.4) ///
        || lowess share_bonds_held_250 size_rank, lcolor(blue) lwidth(medthick) bwidth(.4) ///
    legend(label(3 "Top 100 Investment-Grade Bonds") label(4 "Top 250 Investment-Grade Bonds") ///
        order(3 4) cols(2)) xsize(7) ylab(0(.2)1, angle(0))

graph export "$graphs/holdings_idiosyncrasy_insurers_robustness.pdf", as(pdf) replace
